package com.mashibing.mashibing;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 *
 *
 * 我们看这个小程序，用了一个容器，这个容器是List, 一个一个元素往里装，往里装的时候，
 * 装的堆的数组，一堆的字符串，没100个线程往里面装1000个，各种各样的实现，
 * 可以用ArrayList、 Vector,但是ArrayList会出并发问题，因为多线程访问没有锁，可以用CopyOnWriteArrayList。
 * 这个原理非常简单，当我们需要往里面加元素的时候你把里面的元素得复制出来。在很多情况下，写的时候特别少，读的时候很多。
 *
 * 在这个时候就可以考虑CopyOnWrite这种方式来提高效率，CopyOnWrite为什么会提高效率呢，是因为我写的时候不加锁，
 * 大家知道我Vector写的时候加锁，读的时候也加锁。那么用CopyOnWriteList的时候我读的时候不加锁，
 * 写的时候会在原来的基础上拷贝一个，拷贝的时候扩展出一个新元素来，
 * 然后把你新添加的这个扔到这个元素扔到最后这个位置上，于此同时把指向老的容器的一个引用指向新的，这个写法就是写时复制。
 *
 *
 * 在读比较多写比较少的情况下使用CopyOnWrite
 */
public class T_CopyOnWriteList {

    public static void main(String[] args) {
        List<String> lists =
                //new ArrayList<>(); //这个会出并发问题！
                new Vector();
//                new CopyOnWriteArrayList<>();
        Random r = new Random();
        Thread[] ths = new Thread[100];

        for (int i = 0; i < ths.length; i++) {
            Runnable task = () -> {
                for (int i1 = 0; i1 < 1000; i1++) {
                    lists.add("a" + r.nextInt(10000));
                }
            };
            ths[i] = new Thread(task);
        }


        runAndComputeTime(ths);

        System.out.println(lists.size());
    }

    static void runAndComputeTime(Thread[] ths) {
        long s1 = System.currentTimeMillis();
        Arrays.asList(ths).forEach(t -> t.start());
        Arrays.asList(ths).forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        long s2 = System.currentTimeMillis();
        System.out.println(s2 - s1);

    }
}
